package com.ts.api.http.receive.biz;

import com.gitee.apanlh.util.base.ChooseEq;
import com.gitee.apanlh.util.base.MapUtils;
import com.gitee.apanlh.util.dataformat.JsonUtils;
import com.gitee.apanlh.util.reflection.CopyUtils;
import com.gitee.apanlh.util.valid.Assert;
import com.gitee.apanlh.util.valid.ValidParam;
import com.gitee.apanlh.web.model.vo.RequestVO;
import com.ts.api.common.constant.api.ApiEnum;
import com.ts.api.common.util.ApiDictUtils;
import com.ts.api.exp.ApiMsgException;
import com.ts.api.http.receive.entity.apply.req.ApiReceiveApplyJiKeYouQian;
import com.ts.api.http.receive.entity.dataexchange.req.ApiReceiveDataExchangeJiKeYouQian;
import com.ts.api.module.api.convert.core.annotation.ApiReceive;
import com.ts.api.module.api.convert.core.annotation.ApiReceiveConvertType;
import com.ts.api.module.api.convert.receive.entity.ApiReceiveApply;
import com.ts.api.module.api.convert.receive.entity.ApiReceiveDecrypt;
import com.ts.api.module.api.convert.receive.entity.ApiReceiveNotice;
import com.ts.api.module.api.convert.receive.entity.ApiReceivePhoneMd5DataExchange;
import com.ts.api.module.api.convert.receive.handler.ApiReceivePhoneMd5ConvertHandler;
import com.ts.api.module.api.entity.ApiUserRequest;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Map;

/**
 * 吉客有钱
 * https://x8afj70u7m.feishu.cn/docx/N38SdSzqUoFvhdxykyPcAWmGnSd?from=from_copylink
 * @author 李源聪
 *
 */
@ApiReceive(apiClientId = "1931752808222969856",type = ApiReceiveConvertType.API_CHANNEL_PHONE_MD5)
public class ApiReceivePhoneMd5JiKeYouQian implements ApiReceivePhoneMd5ConvertHandler {

    private static final String KEY = "65ee932741b842dd82c51b48e948cc0e";
    private static final String IV = "01234567";

    @Override
    public Map<String, String> requireParam(RequestVO requestVO) throws Exception {

        //  获取请求体参数
        Map<String, Object> map = JsonUtils.toMap(requestVO.getBody());
        String merchantNo = String.valueOf(map.get("merchantNo"));
        String timestamp = String.valueOf(map.get("timestamp"));
        String reqId = String.valueOf(map.get("reqId"));
        String data = String.valueOf(map.get("data"));

        //  传递什么，验证什么Key
        Assert.isNotEmptyThrows(merchantNo, new ApiMsgException(ApiEnum.API_RECEIVE_BODY_MISS.format("merchantNo")));
        Assert.isNotEmptyThrows(timestamp, new ApiMsgException(ApiEnum.API_RECEIVE_BODY_MISS.format("timestamp")));
        Assert.isNotEmptyThrows(reqId, new ApiMsgException(ApiEnum.API_RECEIVE_BODY_MISS.format("reqId")));
        Assert.isNotEmptyThrows(data, new ApiMsgException(ApiEnum.API_RECEIVE_BODY_MISS.format("data")));

        //  返回需要的数据Map
        return MapUtils.newHashMap(newMap -> {
            newMap.put("merchantNo", merchantNo);
            newMap.put("timestamp", timestamp);
            newMap.put("reqId", reqId);
            newMap.put("data", data);
        });
    }

    @Override
    public ApiReceiveDecrypt decrypt(Map<String, String> paramMap, RequestVO requestVO) throws Exception {
        String data = paramMap.get("data");
        return new ApiReceiveDecrypt(decrypt(data, KEY));
    }

    @Override
    public ApiUserRequest parseDataExchange(ApiReceiveDecrypt apiReceiveDecrypt) throws Exception {
        ApiReceiveDataExchangeJiKeYouQian parse = apiReceiveDecrypt.parse(ApiReceiveDataExchangeJiKeYouQian.class);
        //  拷贝成系统的实体类
        ApiUserRequest apiUserRequest = CopyUtils.copy(parse, ApiUserRequest.class);
        fieldMapping(apiUserRequest);
        return apiUserRequest;
    }

    @Override
    public Map<String, Object> respDataExchange(ApiReceivePhoneMd5DataExchange dataExchangeMessage) throws Exception {
        Map<String, Object> resultMap = MapUtils.newLinkedHashMap();
        boolean suc = dataExchangeMessage.hasBizSuc();
        if (!suc) {
            resultMap.put("dealStatus", "9999");
            resultMap.put("dealDesc", dataExchangeMessage.getBizMsg());
            return resultMap;
        }
        resultMap.put("dealStatus", "0000");
        resultMap.put("dealDesc", "撞库成功");
        resultMap.put("partnerInfo", MapUtils.newLinkedHashMap(dataMap -> {
            //设置下游名称
            dataMap.put("partnerName", dataExchangeMessage.getOrgName());
        }));
        return resultMap;
    }

    @Override
    public ApiUserRequest parseApply(ApiReceiveDecrypt apiReceiveDecrypt) throws Exception {
        ApiReceiveApplyJiKeYouQian parse = apiReceiveDecrypt.parse(ApiReceiveApplyJiKeYouQian.class);
        //  拷贝成系统的实体类
        ApiUserRequest apiUserRequest = CopyUtils.copy(parse, ApiUserRequest.class);
        fieldMapping(apiUserRequest);
        return apiUserRequest;
    }

    @Override
    public Map<String, Object> respApply(ApiReceiveApply applyMessage) throws Exception {
        Map<String, Object> resultMap = MapUtils.newLinkedHashMap();
        boolean suc = applyMessage.hasBizSuc();
        if (!suc) {
            resultMap.put("dealStatus", "9999");
            resultMap.put("dealDesc", applyMessage.getBizMsg());
            return resultMap;
        }
        resultMap.put("dealStatus", "0000");
        resultMap.put("dealDesc", "进件成功");
        return resultMap;
    }

    @Override
    public void fieldMapping(ApiUserRequest apiUserRequest) {
        //年龄转换
        String age = ApiDictUtils.convertAge(apiUserRequest.getAge());
        apiUserRequest.setAge(age);

        // sex 性别 1：男；2：女
        // sex 性别
        // 0 男
        // 1 女
        // 2 未知
        String sex = apiUserRequest.getSex();
        if (ValidParam.isNotEmpty(sex)) {
            String value = ChooseEq.create()
                    .when(sex, "1", "0")  // 男性转换
                    .when(sex, "2", "1")  // 女性转换
                    .end();
            apiUserRequest.setSex(value);
        }

        // loanAmount 客户借款额度 1-0-3万 2-3-5万 3-5-10万 4-0-20万 5-20万以上
        // loanAmount 贷款金额
        // 1.3万以下
        // 2.5万-10万
        // 3.10万-20万
        // 4.20万以上
        String loanAmount = apiUserRequest.getLoanAmount();
        if (ValidParam.isNotEmpty(loanAmount)) {
            String value = ChooseEq.create()
                    .when(loanAmount, "1", "1")
                    .when(loanAmount, "2", "1")
                    .when(loanAmount, "3", "2")
                    .when(loanAmount, "4", "3")
                    .when(loanAmount, "5", "4")
                    .end();
            apiUserRequest.setLoanAmount(value);
        }

        // profession 职业身份 1-自有职业 2-上班族 3-个体户 4-企业主
        // career 职业
        // 1.上班族
        // 2.自由职业
        // 3.企业主（有营业执照）
        // 4.公务员或事业单位
        // 5.个体户
        String career = apiUserRequest.getCareer();
        if (ValidParam.isNotEmpty(career)) {
            String value = ChooseEq.create()
                    .when(career, "1", "2")
                    .when(career, "2", "1")
                    .when(career, "3", "5")
                    .when(career, "4", "3")
                    .end();
            apiUserRequest.setCareer(value);
        }

        // salaryType 工资情况 1-现金收入 2-打卡工资
        // salaryPayMethod 收入形式
        // 1 银行代发打卡
        // 2 现金收入
        // 3 个人转账
        String salaryPayMethod = apiUserRequest.getSalaryPayMethod();
        if (ValidParam.isNotEmpty(salaryPayMethod)) {
            String value = ChooseEq.create()
                    .when(salaryPayMethod, "1", "2")
                    .when(salaryPayMethod, "2", "1")
                    .end();
            apiUserRequest.setSalaryPayMethod(value);
        }

        // socialSecurit 社保 0-无 1-6个月以下 2-6个月以上
        // socialSecurity 社保缴纳
        // 1 无社保
        // 2 缴纳6个月以下
        // 3 缴纳6个月以上
        // 4 有社保
        String socialSecurity = apiUserRequest.getSocialSecurity();
        if (ValidParam.isNotEmpty(socialSecurity)) {
            String value = ChooseEq.create()
                    .when(socialSecurity, "0", "1")
                    .when(socialSecurity, "1", "2")
                    .when(socialSecurity, "2", "3")
                    .end();
            apiUserRequest.setSocialSecurity(value);
        }

        // providentFund 公积金 0-无 1-6个月以下 2-6个月以上
        // providentFund 公积金
        // 1.无公积金
        // 2.缴纳6个月以下
        // 3.缴纳6个月以上
        // 4.有公积金
        String providentFund = apiUserRequest.getProvidentFund();
        if (ValidParam.isNotEmpty(providentFund)) {
            String value = ChooseEq.create()
                    .when(providentFund, "0", "1")
                    .when(providentFund, "1", "2")
                    .when(providentFund, "2", "3")
                    .end();
            apiUserRequest.setProvidentFund(value);
        }

        // car 车辆信息 0-无车 1-有按揭车 2-有全款车
        // carInfo 车辆情况
        // 1.无车产
        // 2.有车不抵押
        // 3.有车可抵押
        // 4.有车
        String carInfo = apiUserRequest.getCarInfo();
        if (ValidParam.isNotEmpty(carInfo)) {
            String value = ChooseEq.create()
                    .when(carInfo, "0", "1")
                    .when(carInfo, "1", "3")
                    .when(carInfo, "2", "4")
                    .end();
            apiUserRequest.setCarInfo(value);
        }

        // estate 房产信息 0-无房产 1-按揭房产 2-全款房产
        // realEstateInfo 房产情况
        // 1 无房产
        // 2 有房不抵押
        // 3 有房可抵押
        // 4 有房产
        // 5 有按揭房产
        // 6 有全款房产
        String realEstateInfo = apiUserRequest.getRealEstateInfo();
        if (ValidParam.isNotEmpty(realEstateInfo)) {
            String value = ChooseEq.create()
                    .when(realEstateInfo, "0", "1")
                    .when(realEstateInfo, "1", "5")
                    .when(realEstateInfo, "2", "6")
                    .end();
            apiUserRequest.setRealEstateInfo(value);
        }

        // creditCardLimit 信用卡额度 0-无信用卡 1-3000元以下 2-3000-5000元 3-5000-10000元 4-10000元以上
        // creditLimit 信用卡额度
        // 1 无信用卡
        // 2 3千以下
        // 3 3千-1万
        // 4 1-3万
        // 5 3万以上
        // 6 有信用卡
        String creditLimit = apiUserRequest.getCreditLimit();
        if (ValidParam.isNotEmpty(creditLimit)) {
            String value = ChooseEq.create()
                    .when(creditLimit, "0", "1")
                    .when(creditLimit, "1", "2")
                    .when(creditLimit, "2", "3")
                    .when(creditLimit, "3", "3")
                    .when(creditLimit, "4", "4")
                    .end();
            apiUserRequest.setCreditLimit(value);
        }

        // zhiMaScore 芝麻分 0-无芝麻分 1-600-650分 2-650-700分 3-700分以上
        // sesameCredit 芝麻分
        // 1 600分以下
        // 2 600~649分
        // 3 650~699分
        // 4 700分以上
        String sesameCredit = apiUserRequest.getSesameCredit();
        if (ValidParam.isNotEmpty(sesameCredit)) {
            String value = ChooseEq.create()
                    .when(sesameCredit, "0", "1")
                    .when(sesameCredit, "1", "2")
                    .when(sesameCredit, "2", "3")
                    .when(sesameCredit, "3", "4")
                    .end();
            apiUserRequest.setSesameCredit(value);
        }

        // lifeInsurance 寿险保单 0-无 1-有
        // insurancePolicy 月收入
        // 1 无保险保单
        // 2 缴纳未满1年
        // 3 缴纳1年以上
        // 4 有保险保单
        String insurancePolicy = apiUserRequest.getInsurancePolicy();
        if (ValidParam.isNotEmpty(insurancePolicy)) {
            String value = ChooseEq.create()
                    .when(insurancePolicy, "0", "1")
                    .when(insurancePolicy, "1", "4")
                    .end();
            apiUserRequest.setInsurancePolicy(value);
        }

        // monthIncome 月收入 1000-300000 (单位元,以1000递增)
        // monthlySalary 月收入
        // 1 1000-3000
        // 2 3000-8000
        // 3 8000~15000
        // 4 15000~30000
        // 5 30000以上
        String monthlySalary = apiUserRequest.getMonthlySalary();
        if (ValidParam.isNotEmpty(monthlySalary)) {
            String value = ApiDictUtils.convertMonthlySalary(monthlySalary);
            apiUserRequest.setMonthlySalary(value);
        }

        // loanPurpose 借款用途 1-日常消费 2-装修 3-旅游 4-教育培训 5-婚庆
        // loanPurpose 借款用途
        // 1 旅游
        // 2 教育
        // 3 婚庆
        // 4 装修
        // 5 医疗
        // 6 个人消费
        String loanPurpose = apiUserRequest.getLoanPurpose();
        if (ValidParam.isNotEmpty(loanPurpose)) {
            String value = ChooseEq.create()
                    .when(loanPurpose, "1", "6")
                    .when(loanPurpose, "2", "4")
                    .when(loanPurpose, "3", "1")
                    .when(loanPurpose, "4", "2")
                    .when(loanPurpose, "5", "3")
                    .end();
            apiUserRequest.setLoanPurpose(value);
        }

        // degree 学历 1-高中及以下 2-大专 3-本科及以上
        // educationAttainment 学历
        // 1 初中及以下
        // 2 中专
        // 3 高中
        // 4 大专
        // 5 本科
        // 6 研究生及以上
        String educationAttainment = apiUserRequest.getEducationAttainment();
        if (ValidParam.isNotEmpty(educationAttainment)) {
            String value = ChooseEq.create()
                    .when(educationAttainment, "1", "3")
                    .when(educationAttainment, "2", "4")
                    .when(educationAttainment, "3", "5")
                    .end();
            apiUserRequest.setEducationAttainment(value);
        }
    }

    @Override
    public Object reqPullApplyNotice(ApiReceiveNotice apiReceiveNotice) {
        return null;
    }

    @Override
    public boolean respPullApplyNotice(String responseBody) {
        return false;
    }

    @Override
    public Object reqPushApplyNotice(ApiReceiveNotice apiReceiveNotice) {
        return null;
    }

    @Override
    public boolean respPushApplyNotice(String responseBody) {
        return false;
    }


    private static byte[] cipher(String algorithm, String transformation, int opmode, byte[] data, byte[] iv, byte[] secretKey) {
        try {
            Key key = SecretKeyFactory.getInstance(algorithm).generateSecret(new DESedeKeySpec(secretKey));
            IvParameterSpec spec = new IvParameterSpec(iv);
            Cipher cipher = Cipher.getInstance(transformation);
            cipher.init(opmode, key, spec);
            return cipher.doFinal(data);
        } catch (InvalidKeyException | InvalidKeySpecException | NoSuchAlgorithmException
                 | NoSuchPaddingException
                 | IllegalBlockSizeException | BadPaddingException |
                 InvalidAlgorithmParameterException e) {
            throw new RuntimeException(e);
        }
    }

    private static byte[] tripleDES(int opmode, byte[] data, byte[] secretKey) {
        return cipher("DESede", "DESede/CBC/PKCS5Padding", opmode, data, IV.getBytes(), secretKey);
    }

    private static String decrypt(String data, String key) {
        try {
            byte[] decoded = Base64.decodeBase64(data); // Base64 解码
            byte[] decrypted = tripleDES(Cipher.DECRYPT_MODE, decoded, key.getBytes());// 3DES 解密
            return new String(decrypted, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}
